package com.eat.fish_service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eat.common_utils.R;
import com.eat.common_utils.ResultCode;
import com.eat.fish_service.entity.AquariumMes;
import com.eat.fish_service.entity.Dao.*;
import com.eat.fish_service.entity.VO.AquariumIds;
import com.eat.fish_service.entity.VO.AquariumVo;
import com.eat.fish_service.entity.VO.IpPortVo;
import com.eat.fish_service.mapper.AquariumMapper;
import com.eat.fish_service.netty_client.ManageConnections;
import com.eat.fish_service.service.*;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author CZF
 * @since 2022-03-21
 */
@Slf4j
@Service
public class AquariumServiceImpl extends ServiceImpl<AquariumMapper, Aquarium> implements AquariumService {

    @Autowired
    IpAndPortService ipAndPortService;

    @Autowired
    UserService userService;

    @Autowired
    UserAquariumService userAquariumService;

    @Autowired
    EquipmentService equipmentService;

    @Autowired
    FishService fishService;

    @Autowired
    SensorDataService sensorDataService;

    @Autowired
    FishNumService fishNumService;

    //管理员添加鱼缸
    @Transactional
    @Override
    public R addEquipment(String charge, IpPortVo ipPortVo) {

        QueryWrapper<IpAndPort> wrapper = new QueryWrapper<>();
        wrapper.eq("ip", ipPortVo.getIp());
        wrapper.eq("port", ipPortVo.getPort());
        IpAndPort one = ipAndPortService.getOne(wrapper);

        //如果数据库中不存在，则插入，若已存在，不能插入
        if (one == null) {

            //鱼缸表
            Aquarium aquarium = new Aquarium();
            aquarium.setCharge(charge);
            //System.out.println("插入前："+aquarium.getId());
            baseMapper.insert(aquarium);
            //System.out.println("插入后："+aquarium.getId());

            //鱼缸ip端口表
            IpAndPort ipAndPort = new IpAndPort();
            BeanUtils.copyProperties(ipPortVo, ipAndPort);
            ipAndPort.setAquariumId(aquarium.getId());

            ipAndPortService.getBaseMapper().insert(ipAndPort);

            //鱼缸设备表
            List<Equipment> list = new ArrayList<>();
            list.add(new Equipment(aquarium.getId(), "蜂鸣器", 0, "https://m.tb.cn/h.fpkwCuj?tk=ps5m2hDT3gY"));
            list.add(new Equipment(aquarium.getId(), "白灯", 0, "https://m.tb.cn/h.fpkwCuj?tk=ps5m2hDT3gY"));
            list.add(new Equipment(aquarium.getId(), "蓝灯", 0, "https://m.tb.cn/h.fpkwCuj?tk=ps5m2hDT3gY"));
            list.add(new Equipment(aquarium.getId(), "橙灯", 0, "https://m.tb.cn/h.fpkwCuj?tk=ps5m2hDT3gY"));
            list.add(new Equipment(aquarium.getId(), "打氧设备", 0, "https://m.tb.cn/h.fLB6p99?tk=yOAh2SPygWo"));
            list.add(new Equipment(aquarium.getId(), "投喂器", 0, "购买地址xxx/型号xxx"));
            list.add(new Equipment(aquarium.getId(), "紫外灯", 0, "购买地址xxx/型号xxx"));
            list.add(new Equipment(aquarium.getId(), "排水阀", 0, "购买地址xxx/型号xxx"));
            list.add(new Equipment(aquarium.getId(), "进水阀", 0, "https://m.tb.cn/h.fpkwCuj?tk=ps5m2hDT3gY"));
            list.add(new Equipment(aquarium.getId(), "监控设备", 0, "监控地址xxx"));
            list.add(new Equipment(aquarium.getId(), "鱼病识别设备", 0, "设备地址xxx"));
            //传感器默认存在，而且不需要通过用户控制开关，所以不添加进设备表

            //循环把设备插入表中
            for (Equipment e : list) {
                equipmentService.getBaseMapper().insert(e);
            }

            //鱼缸鱼数表：
            FishNum fishNum = new FishNum();
            fishNum.setAquariumid(aquarium.getId());
            fishNum.setFishNum(0);
            fishNumService.getBaseMapper().insert(fishNum);

            //添加鱼缸成功后，返回鱼缸id
            return R.ok().data("aquarium_id", aquarium.getId());
        } else {
            return R.error().message("此ip和端口的鱼缸已存在！");

        }

    }

    //用户添加或重连鱼缸
    @Override
    public R addOrRestart(Long aquariumId, String username) {

        //如果此鱼缸已经被人添加，则不能再添加！
        UserAquarium userAquariumCheck = userAquariumService.getOne(new QueryWrapper<UserAquarium>().eq("aquarium_id", aquariumId));
        if (userAquariumCheck != null && !userAquariumCheck.getUsername().equals(username)) {
            return R.error().code(ResultCode.BELONGED).message("该鱼缸已拥有用户");
        }

        IpAndPort ipAndPort = ipAndPortService.getBaseMapper().selectById(aquariumId);

        if (ipAndPort == null) return R.error().code(ResultCode.NOT_FOUND).message("输入id的鱼缸不存在");

        //如果连接管理中有此连接，netty客户端不必要再连接，防止增加netty客户端的压力，也防止水质数据重复添加（鱼缸每一条连接都会每十分钟发送一次数据，如果有多条连接，那样就会发送太多数据）。
        if (ManageConnections.channelList.get(aquariumId) == null) {  //如果没有连接，则建立连接
            //让服务器的netty客户端连接鱼缸的netty服务器
            ChannelFuture channelFuture = ManageConnections.bootstrap.connect(ipAndPort.getIp(), ipAndPort.getPort());

            final boolean[] ifsuccess = {true};

            //使用lamda简化函数式接口的重写
            try {
                channelFuture.addListener((ChannelFutureListener) channelFuture1 -> {
                    if (channelFuture1.isSuccess()) {

                        //往连接管理集合中添加
                        //连接成功后，加入map中，便于接口操作硬件
                        ManageConnections.channelList.put(aquariumId, channelFuture.channel());

                    } else {
                        //重写函数式接口方法，不能调用外部的普通局部变量，所以把boolean改变成数组
                        ifsuccess[0] = false;
                    }
                }).sync();//sync(): 同步操作，连接返回后再执行后面代码
            } catch (Exception e) {
                e.printStackTrace();
                log.error("连接失败！");
                return R.error().message("鱼缸的服务器无法连接，请查看鱼缸服务器是否启动");
            }

            //如果连接成功
            if (ifsuccess[0]) {

                //如果用户鱼缸表中还没添加此记录，没有就添加
                if (ifAdd(aquariumId, username)) {
                    //更新用户鱼缸连接表，让鱼缸绑定用户
                    UserAquarium userAquarium = new UserAquarium();
                    userAquarium.setUsername(username);
                    userAquarium.setAquariumId(aquariumId);
                    userAquariumService.getBaseMapper().insert(userAquarium);

                }
                //更新鱼缸的ip表的is_connected，用来表示该鱼缸已被连接
                ipAndPort.setIsConnected(1);
                ipAndPortService.updateById(ipAndPort);


                return R.ok();
            } else {
                return R.error().message("鱼缸的服务器无法连接，请查看鱼缸服务器是否启动");
            }
        } else {                //如果有连接，则不需要连接，只需把该鱼缸加给用户
            if (ifAdd(aquariumId, username)) {
                //更新用户鱼缸连接表，让鱼缸绑定用户
                UserAquarium userAquarium = new UserAquarium();
                userAquarium.setUsername(username);
                userAquarium.setAquariumId(aquariumId);
                userAquariumService.getBaseMapper().insert(userAquarium);
            }
            return R.ok();
        }


    }

    @Override
    public R aquariumMess(Long aquariumId) {
        //鱼缸信息
        Aquarium aquarium = baseMapper.selectById(aquariumId);

        //负责人信息
        User charge = userService.getOne(new QueryWrapper<User>().eq("username", aquarium.getCharge()));

        //netty发送消息给硬件通知硬件更新数据,如果更新失败，则使用最新数据返回
        boolean update = ManageConnections.updateData(aquariumId);

        if (update) {
            //传感器数据
            QueryWrapper<SensorData> wrapper = new QueryWrapper<>();
            wrapper.eq("a_id", aquariumId);
//        wrapper.orderByDesc("data_id");
            wrapper.last("limit 1");
            List<SensorData> senorDatas = sensorDataService.list(wrapper);

            AquariumVo aquariumVo = new AquariumVo();


            aquariumVo.setFishNum(aquarium.getFishNum());    //鱼的数量
            aquariumVo.setMaxNum(aquarium.getMaxNum()); //最大容量
            aquariumVo.setCharge(aquarium.getCharge()); //负责人姓名
            aquariumVo.setPhone(charge.getPhone()); //负责人电话

            BeanUtils.copyProperties(senorDatas.get(0), aquariumVo);//传感器数据

            System.out.println(aquariumVo);

            return R.ok().data("aquariumMess", aquariumVo);
        } else {
            //传感器数据
            QueryWrapper<SensorData> wrapper = new QueryWrapper<>();
            wrapper.eq("a_id", aquariumId);
            wrapper.orderByDesc("data_id");
            wrapper.last("limit 1");
            List<SensorData> senorDatas = sensorDataService.list(wrapper);

            AquariumVo aquariumVo = new AquariumVo();

            aquariumVo.setFishNum(aquarium.getFishNum());    //鱼的数量
            aquariumVo.setCharge(aquarium.getCharge()); //负责人姓名
            aquariumVo.setMaxNum(aquarium.getMaxNum());
            aquariumVo.setPhone(charge.getPhone()); //负责人电话

            BeanUtils.copyProperties(senorDatas.get(0), aquariumVo);//传感器数据

            System.out.println(aquariumVo);

            return R.ok().code(ResultCode.UPDATE_FAILURE).data("aquariumMess", aquariumVo);
        }


    }

    //返回所有鱼缸信息
    @Override
    public R allAquariumMess() {
        List<AquariumMes> aquariumMesList = baseMapper.allAquariumMess();
        return R.ok().data("allAquarium", aquariumMesList);
    }

    //修改鱼的最大数量
    @Override
    public R editMaxFishNum(Long aquariumId, Integer maxNum) {
        Aquarium aquarium = new Aquarium();
        aquarium.setId(aquariumId);
        aquarium.setMaxNum(maxNum);
        int i = baseMapper.updateById(aquarium);
        if (i < 1) {
            return R.error().message("更新失败！");
        } else {
            return R.ok().data("maxNum", maxNum);
        }
    }

    @Override
    public R delUserAquarium(String username, AquariumIds aquariumIds) {

        List<Long> list = aquariumIds.getAquariumIds();

        if (list.size() == 0) {
            return R.error().message("鱼缸id不能为空！");
        }

        for (Long aquariumId : list) {
            userAquariumService.getBaseMapper().delete(new QueryWrapper<UserAquarium>().eq("username", username).eq("aquarium_id", aquariumId));
        }
        return R.ok();

    }

    //检查用户鱼缸表是否添加此记录
    public boolean ifAdd(Long aquariumId, String username) {
        QueryWrapper<UserAquarium> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        wrapper.eq("aquarium_id", aquariumId);
        int num = userAquariumService.count(wrapper);


        log.info(String.valueOf(num));

        return num == 0;
    }
}
